import time
from functools import wraps
from loguru import logger

def print_time(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        logger.info(f"{func.__name__} executed in {end_time - start_time:.2f} seconds")
        return result

    return wrapper

def cache(ttl_seconds=300, max_keys=500):
    """
    Cache decorator that caches function results based on input parameters.

    Args:
        ttl_seconds (int): Time to live for cached items in seconds, defaults to 300
        max_keys (int): Maximum number of keys to store in cache, defaults to 1000
    """
    # Validate and set default parameters
    if ttl_seconds is None or ttl_seconds <= 0:
        ttl_seconds = 300
    if max_keys is None or max_keys <= 0:
        max_keys = 100

    cache_dict = {}
    cache_times = {}

    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            try:
                args_str = str([str(arg) if arg is not None else 'None' for arg in args])
                kwargs_str = str(sorted([(k, str(v) if v is not None else 'None')
                                         for k, v in kwargs.items()]))
                key = args_str + kwargs_str

                current_time = time.time()
                if key in cache_dict:
                    if current_time - cache_times[key] < ttl_seconds:
                        logger.info(f"Func {func.__name__} hit cache")
                        return cache_dict[key]
                    else:
                        del cache_dict[key]
                        del cache_times[key]

                result = func(*args, **kwargs)

                if len(cache_dict) >= max_keys:
                    try:
                        oldest_key = min(cache_times, key=cache_times.get)
                        del cache_dict[oldest_key]
                        del cache_times[oldest_key]
                    except ValueError:
                        pass

                cache_dict[key] = result
                cache_times[key] = current_time
                return result
            except Exception as e:
                logger.error(f"Error in cached function {func.__name__}: {str(e)}")
                raise e

        return wrapper

    return decorator
